package com.aceleeyy.sevenstar.controller;

import com.aceleeyy.sevenstar.config.ErrorMessage;
import com.aceleeyy.sevenstar.config.SevenStarCommonInfo;
import com.aceleeyy.sevenstar.dao.MagazineMapper;
import com.aceleeyy.sevenstar.dao.MagazinePicturesMapper;
import com.aceleeyy.sevenstar.model.Magazine;
import com.aceleeyy.sevenstar.model.MagazinePictures;
import com.aceleeyy.sevenstar.model.Result;
import com.aceleeyy.sevenstar.utils.ItextpdfUtil;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;

/**
 * 文件管理
 *
 * @auther: Ace Lee
 * @date: 2019/10/26 10:43
 */
@Api(value = "文件管理", description = "文件管理")
@Slf4j
@RestController
@RequestMapping("/files")
public class FileController extends BaseController {

    @Value("${file.save.path}")
    private String filePath;
    @Value("${file.server.path}")
    private String serverPath;
    @Value("${file.show.path}")
    private String showPath;

    @Autowired
    private MagazineMapper magazineMapper;
    @Autowired
    private MagazinePicturesMapper magazinePicturesMapper;

    /**
     * 将pdf保存为杂志表记录
     * 文件名格式：期刊号-文件名
     * 例子：2019.7-七星指南7期（定稿）.pdf
     * 大小：不超过50m
     *
     * @param request
     * @param files
     * @return
     */
    @ApiOperation("pdf转杂志")
    @PostMapping("/upload/pdf")
    public Result uploadPDF(HttpServletRequest request, @RequestParam("files") MultipartFile[] files
            , @RequestParam("type") Integer type, @RequestParam(value = "id",required = false) Integer id) {
        Result result;
        if (files.length <= 0) {
            return Result.error(ErrorMessage.E_001.getErrDesc());
        }

        try {
            //获取multiRequest 中所有的文件名
            Map<String, Object> map = null;
            Magazine magazine = null;
            int count = 0;

            for (MultipartFile file : files) {
                if (file != null) {
                    String fileName = file.getOriginalFilename();
                    String path = filePath + fileName;
                    //上传
                    log.info("文件上传,参数：{}", path);
                    file.transferTo(new File(path));
                    //pdf
                    if (null==type||0==type){
                        map = ItextpdfUtil.getPdfContentAndPages(path);
                        if (null != map && !map.isEmpty()) {
                            magazine = new Magazine();
                            magazine.setTitle(fileName.substring(0, fileName.lastIndexOf(".")));
                            magazine.setMagazinePage(0);
                            magazine.setIsInBooklist(SevenStarCommonInfo.BOOLEAN_NO);
//                            magazine.setContent((String) map.get("content"));
                            magazine.setFileContent(serverPath + fileName);
                            magazine.setFilePages((Integer) map.get("count"));
                            magazine.setIssn(fileName.substring(0, fileName.lastIndexOf("-")));
                            magazine.setIsValid(SevenStarCommonInfo.BOOLEAN_YES);
                            magazine.setCreatedTime(new Date());
                            magazine.setCreatedUser("user1");
                            int add = magazineMapper.insertSelective(magazine);
                            log.info("文件保存杂志{},结果：{}", fileName, add);
                            count++;
                        }
                    //内容图片
                    }else if (1==type){
                        MagazinePictures mp = new MagazinePictures();
                        mp.setMagazineId(id);
                        mp.setPageNo(1);
                        mp.setPicture(showPath+fileName);
                        mp.setCreatedTime(new Date());
                        mp.setCreatedUser("user1");
                        int save = magazinePicturesMapper.insertSelective(mp);
                        log.info("文件保存杂志内容图片{},结果：{}", fileName, save);
                        count++;
                    }
                }
            }
            log.info("文件上传，结果：{}", count);
            result = new Result<>(count);
        } catch (IOException e) {
            log.error("文件上传，异常：{}", Throwables.getStackTraceAsString(e));
            result = Result.error(ErrorMessage.E_999.getErrDesc());
        }
        return result;
    }

    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public Result upload(HttpServletRequest request, @RequestParam("files") MultipartFile[] files) {
        Result result;
        if (files.length <= 0) {
            return Result.error(ErrorMessage.E_001.getErrDesc());
        }

        try {
            //获取multiRequest 中所有的文件名
            Map<String, Object> map = Maps.newHashMap();
            for (MultipartFile file : files) {
                if (file != null) {
                    String fileName = file.getOriginalFilename();
                    String path = filePath + fileName;
                    //上传
                    log.info("文件上传,参数：{}", path);
                    file.transferTo(new File(path));
                    map.put(fileName, serverPath + fileName);
                }
            }

            log.info("文件上传，结果：{}", map);
            result = new Result<>(map);
        } catch (IOException e) {
            log.error("文件上传，异常：{}", Throwables.getStackTraceAsString(e));
            result = Result.error(ErrorMessage.E_999.getErrDesc());
        }
        return result;
    }

    @ApiOperation("文件展示")
    @GetMapping("")
    public void show(@RequestParam("filename") String filename, HttpServletResponse httpServletResponse) throws IOException {
        if (StringUtils.isEmpty(filename)) {
            return;
        }
        log.info("文件展示，请求参数：{}", filename);
        String path = filePath + filename;
        File file = new File(path);
        if (!file.exists()) {
            return;
        }

        InputStream in = new FileInputStream(file);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }


    /*@ApiOperation("pdf展示")
    @GetMapping("pdf")
    public void showPDF(@RequestHeader(value = "Range") String range,@RequestParam("filename") String filename,
                        HttpServletResponse response) throws IOException {
        if (StringUtils.isEmpty(filename)) {
            return;
        }
        log.info("文件展示，请求参数：{}", filename);
        String path = filePath + filename;
        File file = new File(path);
        if (!file.exists()) {
            return;
        }

        //开始下载位置
        long startByte = 0;
        //结束下载位置
        long endByte = file.length() - 1;

        //有range的话
        if (range != null && range.contains("bytes=") && range.contains("-")) {
            range = range.substring(range.lastIndexOf("=") + 1).trim();
            String ranges[] = range.split("-");
            try {
                //根据range解析下载分片的位置区间
                if (ranges.length == 1) {
                    //情况1，如：bytes=-1024  从开始字节到第1024个字节的数据
                    if (range.startsWith("-")) {
                        endByte = Long.parseLong(ranges[0]);
                    }
                    //情况2，如：bytes=1024-  第1024个字节到最后字节的数据
                    else if (range.endsWith("-")) {
                        startByte = Long.parseLong(ranges[0]);
                    }
                }
                //情况3，如：bytes=1024-2048  第1024个字节到2048个字节的数据
                else if (ranges.length == 2) {
                    startByte = Long.parseLong(ranges[0]);
                    endByte = Long.parseLong(ranges[1]);
                }

            } catch (NumberFormatException e) {
                startByte = 0;
                endByte = file.length() - 1;
            }
        }

        //要下载的长度
        long contentLength = endByte - startByte + 1;

        //【分片】https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Ranges
        response.setHeader("Accept-Ranges", "bytes");
        //【跨域】
        response.setHeader("Access-Control-Allow-Origin", "*");
        //【分片】Content-Length 表示资源内容长度，即：文件大小
        response.setHeader("Content-Length", String.valueOf(contentLength));
        Date date = new Date();

        //【浏览器缓存】设置缓存周期为24个小时
        Long cacheCycle = (long) (24 * 60 * 60 * 1000);

        Long time = date.getTime() + cacheCycle;

        //【浏览器缓存】Last-Modified:页面的最后生成时间
        response.setDateHeader("Last-Modified", date.getTime());

        //【浏览器缓存】Expires:过时期限值
        response.setDateHeader("Expires", time);

        //【浏览器缓存】Cache-Control来控制页面的缓存与否,public:浏览器和缓存server都能够缓存页面信息
        response.setHeader("Cache-Control", "public");

        //【浏览器缓存】Pragma:设置页面是否缓存，为Pragma则缓存，no-cache则不缓存
        response.setHeader("Pragma", "Pragma");
        //【分片】
        response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));// 设置在下载框默认显示的文件名
        //【分片】Content-Range 表示响应了多少数据，格式为：[要下载的开始位置]-[结束位置]/[文件总大小]
        response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + file.length());
        //【浏览器缓存】
        response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
        // 读出文件到response
        // 这里是先需要把要把文件内容先读到缓冲区
        // 再把缓冲区的内容写到response的输出流供用户下载
        *//*FileInputStream fileInputStream = new FileInputStream(file);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        OutputStream outputStream = response.getOutputStream();
        byte buffer[] = new byte[1024];
        int len = 0;
        while ((len = bufferedInputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, len);
        }
        // 人走带门
        bufferedInputStream.close();
        outputStream.flush();
        outputStream.close();*//*
        BufferedOutputStream outputStream = null;
        RandomAccessFile randomAccessFile = null;
        //已传送数据大小
        long transmitted = 0;
        try {
            randomAccessFile = new RandomAccessFile(file, "r");
            outputStream = new BufferedOutputStream(response.getOutputStream());
            byte[] buff = new byte[2048];
            int len = 0;
            randomAccessFile.seek(startByte);
            //判断是否到了最后不足2048（buff的length）个byte
            while ((transmitted + len) <= contentLength && (len = randomAccessFile.read(buff)) != -1) {
                outputStream.write(buff, 0, len);
                transmitted += len;
            }
            //处理不足buff.length部分
            if (transmitted < contentLength) {
                len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
                outputStream.write(buff, 0, len);
                transmitted += len;
            }

            outputStream.flush();
            response.flushBuffer();
            randomAccessFile.close();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }*/

    @ApiOperation("pdf展示")
    @GetMapping("pdf")
    public void showPDF(@RequestParam("filename") String filename,
                        HttpServletResponse response) throws IOException {
        if (StringUtils.isEmpty(filename)) {
            return;
        }
        log.info("文件展示，请求参数：{}", filename);
        String path = filePath + filename;
        File file = new File(path);
        if (!file.exists()) {
            return;
        }

        //【分片】https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Ranges
        response.setHeader("Accept-Ranges", "bytes");
        //【跨域】
        response.setHeader("Access-Control-Allow-Origin", "*");
        //【分片】Content-Length 表示资源内容长度，即：文件大小
        response.setHeader("Content-Length", String.valueOf(file.length()));
        Date date = new Date();

        //【浏览器缓存】设置缓存周期为24个小时
        Long cacheCycle = (long) (24 * 60 * 60 * 1000);

        Long time = date.getTime() + cacheCycle;

        //【浏览器缓存】Last-Modified:页面的最后生成时间
        response.setDateHeader("Last-Modified", date.getTime());

        //【浏览器缓存】Expires:过时期限值
        response.setDateHeader("Expires", time);

        //【浏览器缓存】Cache-Control来控制页面的缓存与否,public:浏览器和缓存server都能够缓存页面信息
        response.setHeader("Cache-Control", "public");

        //【浏览器缓存】Pragma:设置页面是否缓存，为Pragma则缓存，no-cache则不缓存
        response.setHeader("Pragma", "Pragma");
        //【分片】
        response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));// 设置在下载框默认显示的文件名
        //【分片】Content-Range 表示响应了多少数据，格式为：[要下载的开始位置]-[结束位置]/[文件总大小]
//        response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + file.length());
        //【浏览器缓存】
        response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
        // 读出文件到response
        // 这里是先需要把要把文件内容先读到缓冲区
        // 再把缓冲区的内容写到response的输出流供用户下载
        FileInputStream fileInputStream = new FileInputStream(file);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        OutputStream outputStream = response.getOutputStream();
        byte buffer[] = new byte[1024];
        int len = 0;
        while ((len = bufferedInputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, len);
        }
        // 人走带门
        bufferedInputStream.close();
        outputStream.flush();
        outputStream.close();

    }

}
